

//===============================================================

/*var CalculatorMixin = Base => class extends Base {  
    calc() {  
        console.log("calc");  
    }  
};  
  
var RandomizerMixin = Base => class extends Base {  
    randomize() {  
        console.log("randomize");  
    }  
};  
  
class Foo {   
    foo(){  
        console.log("foo");  
    }  
}  
class Bar extends CalculatorMixin(RandomizerMixin(Foo)) { }  
  
var b = new Bar();  
b.foo();  
b.randomize();  
b.calc(); 

console.log(b instanceof Foo);
//console.log(b instanceof RandomizerMixin);
//console.log(b instanceof CalculatorMixin);*/


function Multi(base,...others){
    //var result = class extends base{};

    others.reduce(function(prev,cur){
        Object.setPrototypeOf(prev,cur);
        Object.setPrototypeOf(prev.prototype,cur.prototype);
        return cur;
    },base);

    return base;
}

class A{
    constructor(...args){
        //super(...args);
        console.log("A....",args);
    }
    sayA(){
        console.log("A");
    }

}
class B{
    constructor(...args){
        console.log("B....",args);
    }
    sayB(){
        super.sayC();
        console.log("B");
    }
}
class C{
    constructor(...args){
        console.log("C....",args);
    }
    sayC(){
        console.log("C");
    }
}

class Test extends Multi(A,B,C){
    constructor(...args){
        super(...args);
    }
}


var t = new Test(1,2,3);
t.sayA();
t.sayB();
t.sayC();

console.log(t instanceof A);
console.log(t instanceof B);
console.log(t instanceof C);


/*var aggregation = (base, ...mixins) => {


    let aggregate = class __Aggregate extends base {
        constructor (...args) {

            super(...args)



            mixins.forEach((mixin) => {
                if (typeof mixin.prototype.initializer === "function")
                    mixin.prototype.initializer.apply(this, args)
            })
        }
    };


    let copyProps = (target, source) => {
        Object.getOwnPropertyNames(source)
            .concat(Object.getOwnPropertySymbols(source))
            .forEach((prop) => {
            if (prop.match(/^(?:initializer|constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
                return
            Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
        })
    }



    mixins.forEach((mixin) => {
        copyProps(aggregate.prototype, mixin.prototype)
        copyProps(aggregate, mixin)
    })


    return aggregate
}




class Colored {
    initializer ()     { this._color = "white" }
    get color ()       { return this._color }
    set color (v)      { this._color = v }
}


class ZCoord {
    initializer ()     { this._z = 0 }
    get z ()           { return this._z }
    set z (v)          { this._z = v }
}


class Shape {
    constructor (x, y) { this._x = x; this._y = y }
    get x ()           { return this._x }
    set x (v)          { this._x = v }
    get y ()           { return this._y }
    set y (v)          { this._y = v }
}


class Rectangle extends aggregation(Shape, Colored, ZCoord) {
    toString(){
        return this.x+","+this.y+","+this.z+","+this.color;
    }
}


var rect = new Rectangle(7, 42)
rect.z     = 1000
//rect.color = "red"
console.log(rect);
*/


/*function CalculatorMixin(Base){
    return class extends Base { 
        constructor(...args){
            super(...args);
            console.log("CalculatorMixin",args);
        } 
        calc() {  
            console.log("calc");  
        }  
    }
}

function RandomizerMixin(Base){
    return class extends Base { 
        constructor(...args){
            super(...args);
            console.log("RandomizerMixin",args);
        }

        randomize() {
            super.foo();  
            console.log("randomize");  
        } 
    }
}*/

var CalculatorMixin = Base => class extends Base { 
    constructor(...args){
        super(...args);
        console.log("CalculatorMixin",args);
    } 
    calc() {  
        console.log("calc");  
    }  
};  
  
var RandomizerMixin = Base => class extends Base {  
    constructor(...args){
        super(...args);
        console.log("RandomizerMixin",args);
    }
    randomize() {
        super.foo();  
        console.log("randomize");  
    }  
};  

  
class Foo {  
    constructor(...args){
        console.log("Foo",args);
    } 
    foo(){  
        console.log("foo");  
    }  
}  
class Bar extends CalculatorMixin(RandomizerMixin(Foo)) {

}  
  
var b = new Bar(1,2,3);  
b.foo();  
b.randomize();  
b.calc(); 

CalculatorMixin.prototype = Object.create(null);
RandomizerMixin.prototype = Object.create(null);
Object.setPrototypeOf(RandomizerMixin.prototype,CalculatorMixin.prototype)
Object.setPrototypeOf(Foo.prototype,RandomizerMixin.prototype)



console.log(b instanceof Bar)
console.log(b instanceof Foo)
console.log(b instanceof CalculatorMixin)
console.log(b instanceof RandomizerMixin)
console.log(b instanceof Object)

